/*! \file HXRender.h
    \brief Head X model data.

	Head X | Flinders University | Martin Luerssen & Trent Lewis | 2009+
*/

#pragma once

struct HXRGBA;
class HXImageRGBA;
class HXRenderData;

#include "HXUtil.h"
#include "HXMorph.h"
#include "HXMatrix.h" 
#include "HXShader.h"

#define MAX_MORPH_VALUE 1.0f
#define HXR_BUILT_NORMALS 0x00000001
#define HXR_BUILT_TEXTURES 0x00000002
#define HXR_BUILT_SHADERS 0x00000004

//-----------------------------------------------------------------------------

//! Model data.
class HXRenderData
{
public:
	HXRenderData();
	~HXRenderData();
	HXRenderData(HXRenderData const& a_rOther);

	void BuildNormalList();
	void DrawOpaque(HXShader* pShader);
	void DrawTransparent(HXShader* pShader);
	void Draw(HXShader* pShader);
	void UpdateTextures(bool bMipmap);
	void BuildTextures(bool bMipmap);
	void ClearTextures();

	void LoadShaders(const wstring& pshaderFile, const wstring& vshaderFile);
	bool BuildShaders();
	void StartShaders();
	void EndShaders();
	
	HXMorph& Morphs() { return m_morph; }
	void CreateMorphs();
	void ApplyMorphs();

	HXModel& Model() { return m_renderModel; }
	bool& Center() { return m_center; }
	int& RecompNormal() { return m_recompNormal; }
	vector<HXVector3F>& VertexBuffer() 
	{ 
		switch (m_isMorphed)
		{
		case 0:
			return m_renderModel.vertexList;
			break;
		case 1:
			return m_vertexListA;
			break;
		default:
			return m_vertexListB;
			break;
		}
	}

	void SetShininess(float val) 
	{
		for (size_t i = 0; i < Model().materialList.size(); i++)
		{
			Model().materialList[i].specular[0] = Model().materialList[i].specular[1] = Model().materialList[i].specular[2] = val;
			Model().materialList[i].shininess = val*128;
		}
	}
	float GetAlphaThreshold() { return m_renderModel.alphaThreshold; }
	void SetAlphaThreshold(float at) { m_renderModel.alphaThreshold = at; }
	long BuildStatus() { return m_built; }


protected:
	void SetMaterial(HXMaterial& matter, HXShader* pShader);
	void ResetMaterial();

	HXModel m_renderModel;
	HXShader m_shader;
	vector<HXVector3F> m_vertexListA, m_vertexListB;
	volatile long m_isMorphed;
	unsigned int* m_oglTexArray;
	size_t m_oglTexSize;
	vector<HXVector3F> m_normList;
	long m_built;
	bool m_center;
	int m_recompNormal, m_normalFrameCounter;
	
	HXMorph m_morph;
	unsigned int m_VertexShaderObject, m_PixelShaderObject, m_ProgramObject;

	CRITICAL_SECTION	m_criticalSection_Draw;
};

//-----------------------------------------------------------------------------